﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using zEngine;

namespace zEngine
{
    public class zShader
    {
        ContentManager contents;

        private Matrix _world;
        private Matrix _view;
        private Matrix _projection;
        private Vector3 _viewVector;
        private Vector3 _cameraPosition;
        private List<zLight> _lights = new List<zLight>();

        private Effect _effect;
        private string _effectName = "";

        private string _techniqueName = "";

        private Texture2D _diffuseMap;
        private Color _diffuseColor = new Color(207, 207, 207);
        private Color _specularColor = new Color(255, 255, 255);


        /// <summary>
        /// Initializes a new instance of the Shader class.
        /// </summary>
        public zShader()
        {
        }
        public zShader(Effect effect, string effectName)
        {
            _effect = effect;
            _effectName = effectName;
        }

        public void Update()
        {
            // No effect yet. then don't care about the rest
            if (_effect == null) return;
            if (TechniqueName.Length > 0)
            {
                _effect.CurrentTechnique = _effect.Techniques[_techniqueName];
            }
            else
            {
                _effect.CurrentTechnique = _effect.Techniques[0];
            }
            // Positions Info
            SetParameter("World", _world);
            SetParameter("View", _view);
            SetParameter("Projection", _projection);
            SetParameter("WorldViewProj", WorldViewProj);
            SetParameter("ViewVector", _viewVector);
            SetParameter("WorldInverseTranspose", WorldInverseTranspose);
            SetParameter("DiffuseColor", _diffuseColor.ToVector4());
            SetParameter("SpecularColor", _specularColor.ToVector4());
            //SetParameter("CameraPosition", _cameraPosition);
            SetParameter("DiffuseMap", _diffuseMap);
            if (_lights.Count > 0)
            {
                SetParameter("LightViewProj", Lights[0].LightViewProj);
            }
        }

        #region SetParameters

        public void SetParameter(string parameterName, Vector4 value)
        {
            for (int i = 0; i < _effect.Parameters.Count; i++)
            {
                if (_effect.Parameters[i].Name == parameterName)
                {
                    _effect.Parameters[i].SetValue(value);
                    break;
                }
            }
        }
        public void SetParameter(string parameterName, Vector3 value)
        {
            for (int i = 0; i < _effect.Parameters.Count; i++)
            {
                if (_effect.Parameters[i].Name == parameterName)
                {
                    _effect.Parameters[i].SetValue(value);
                    break;
                }
            }
        }
        public void SetParameter(string parameterName, Texture value)
        {
            if (value == null) return;
            for (int i = 0; i < _effect.Parameters.Count; i++)
            {
                if (_effect.Parameters[i].Name == parameterName)
                {
                    _effect.Parameters[i].SetValue(value);
                    break;
                }
            }
        }

        public void SetParameter(string parameterName, Matrix value)
        {
            for (int i = 0; i < _effect.Parameters.Count; i++)
            {
                if (_effect.Parameters[i].Name == parameterName)
                {
                    _effect.Parameters[i].SetValue(value);
                    break;
                }
            }
        }
        public void SetParameter(string parameterName, Matrix[] value)
        {
            for (int i = 0; i < _effect.Parameters.Count; i++)
            {
                if (_effect.Parameters[i].Name == parameterName)
                {
                    _effect.Parameters[i].SetValue(value);
                    break;
                }
            }
        }
        #endregion

        #region Dynamic Properties
        public Matrix WorldViewProj
        {
            get { return _world * _view * _projection; }
        }
        public Matrix WorldInverseTranspose
        {
            get { return Matrix.Transpose(Matrix.Invert(_world)); }
        }
        #endregion

        #region Fixed Properties

        public Vector3 ViewVector
        {
            get { return _viewVector; }
            set { _viewVector = value; }
        }
        public Matrix World
        {
            get { return _world; }
            set { _world = value; }
        }
        public Matrix View
        {
            get { return _view; }
            set { _view = value; }
        }
        public Matrix Projection
        {
            get { return _projection; }
            set { _projection = value; }
        }
        public Vector3 CameraPosition
        {
            get { return _cameraPosition; }
            set { _cameraPosition = value; }
        }
        public Effect Effect
        {
            get
            {
                if (_effect == null && _effectName.Length > 0 && contents != null)
                {
                    _effect = contents.Load<Effect>(_effectName);
                }
                return _effect;
            }
            set { _effect = value; }
        }
        public string EffectName
        {
            get { return _effectName; }
            set { _effectName = value; }
        }
        public Texture2D DiffuseMap
        {
            get { return _diffuseMap; }
            set { _diffuseMap = value; }
        }
        public Color DiffuseColor
        {
            get { return _diffuseColor; }
            set { _diffuseColor = value; }
        }
        public Color SpecularColor
        {
            get { return _specularColor; }
            set { _specularColor = value; }
        }
        public List<zLight> Lights
        {
            get { return _lights; }
            set { _lights = value; }
        }
        public string TechniqueName
        {
            get { return _techniqueName; }
            set { _techniqueName = value; }
        }
        #endregion
    }
}
